package com.example.capsule_netty.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.capsule_netty.bean.RoomBean;
import com.example.capsule_netty.configuration.Constant;
import com.example.capsule_netty.global.GlobalThreadPool;
import com.example.capsule_netty.mapper.MacAddressToFieldMapper;
import com.example.capsule_netty.mapper.RoomMapper;
import com.example.capsule_netty.mapper.UserInfoMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;

/**
 * @Author: zhuzhiming
 * @Date: 2022/5/2 0:07
 */
@Service
public class FieldToMacService {

    @Resource
    MacAddressToFieldMapper macAddressToFieldMapper;
    @Resource
    RoomService roomBeanService;

    @Resource
    RoomMapper roomMapper;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    @Autowired
    UserInfoService userInfoService;

    @SneakyThrows
    public String getFieldByMac(String userId, String macAddress) {

        String field = macAddressToFieldMapper.getFieldByMac(macAddress);

        if (field == null) {
            return Constant.FAIL;
        }
        GlobalThreadPool.buildThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                userInfoService.addFieldRecord(userId, field);
            }
        });


        CompletableFuture<List<RoomBean>> querySecretRoom = CompletableFuture.supplyAsync(() -> {
            QueryWrapper<RoomBean> queryWrapper = new QueryWrapper<RoomBean>().eq("field", field).ne("secret_level", 0);
            List<RoomBean> roomBeanList = roomMapper.selectList(queryWrapper);
            return roomBeanList;
        }).thenApply(secretRoomList -> {
            List<RoomBean> roomBeans = new ArrayList<>();
            secretRoomList.forEach(roomBean -> {
                String key = field + "-" + roomBean.getRoomName() + "-" + "secretMember";
                Boolean member = redisTemplate.opsForSet().isMember(key, userId);
                if (Boolean.TRUE.equals(member)) {
                    roomBeans.add(roomBean);
                }
            });
            return roomBeans;
        });

        CompletableFuture<List<RoomBean>> queryCommonRoom = CompletableFuture.supplyAsync(() -> {
                    String queryFromRedis = redisTemplate.opsForValue().get(field);
                    if (queryFromRedis != null) {
                        return new Gson().fromJson(queryFromRedis, new TypeToken<List<RoomBean>>() {
                        }.getType());
                    }
                    return new ArrayList();
                })
                .thenApply(listFormRedis -> {
                    if (CollectionUtils.isEmpty(listFormRedis)) {
                        List<RoomBean> roomBeanList = roomBeanService.getRoomListByField(field);
                        String roomBeanJson = new Gson().toJson(roomBeanList);
                        redisTemplate.opsForValue().set(field, roomBeanJson, 30, TimeUnit.MINUTES);
                        return roomBeanList;
                    } else {
                        return listFormRedis;
                    }
                });

        CompletableFuture<List<RoomBean>> resFuture = querySecretRoom.thenCombine(queryCommonRoom, new BiFunction<List<RoomBean>, List<RoomBean>, List<RoomBean>>() {
            @Override
            public List<RoomBean> apply(List<RoomBean> roomBeanList, List<RoomBean> roomBeanList2) {
                roomBeanList.addAll(roomBeanList2);
                return roomBeanList;
            }
        });

        List<RoomBean> roomBeanList = resFuture.get();
        return new Gson().toJson(roomBeanList);
    }

}
